#include "uartwork.h"

uartWork::uartWork(comcfg_t cfg) {
  currentCfg.portNum = cfg.portNum;
  currentCfg.baudRate = cfg.baudRate;
  currentCfg.dataBits = cfg.dataBits;
  currentCfg.paritys = cfg.paritys;
  currentCfg.stopBits = cfg.stopBits;
  currentCfg.flowCtrl = cfg.flowCtrl;
  isConnectFlag = false;
  currSerial = new QSerialPort();
  currSerial->setReadBufferSize(1);

  currThread = new QThread();
  rcvDataTimer = new QTimer();
  this->moveToThread(currThread);
  currSerial->moveToThread(currThread);
  rcvDataTimer->moveToThread(currThread);
  connect(currSerial, &QSerialPort::errorOccurred, this,
          &uartWork::errorOccurred);
  connect(currSerial, &QSerialPort::readyRead, this, &uartWork::readyRead,
          Qt::QueuedConnection);
  currThread->start();

  rcvDataTimer->setInterval(30);
  rcvDataTimer->setTimerType(Qt::PreciseTimer);
  connect(rcvDataTimer, &QTimer::timeout, this, &uartWork::timerOut,
          Qt::QueuedConnection);
}

uartWork::~uartWork() {
  rcvDataTimer->stop();
  delete rcvDataTimer;
  if (currSerial->isOpen()) {
    currSerial->clear();
    currSerial->close();
    emit openError(false);
  }

  if (currThread->isRunning()) {
    currThread->quit();
    while (true == currThread->isRunning())
      ;
  }
  currSerial->deleteLater();
  currThread->deleteLater();
}

void uartWork::updateComCfg(comcfg_t cfg) {
  currentCfg.portNum = cfg.portNum;
  currentCfg.baudRate = cfg.baudRate;
  currentCfg.dataBits = cfg.dataBits;
  currentCfg.paritys = cfg.paritys;
  currentCfg.stopBits = cfg.stopBits;
  currentCfg.flowCtrl = cfg.flowCtrl;
  /* 通知打开串口 */
  openUart();
  // startThread();
}

void uartWork::startThread() {
  if (false == currThread->isRunning()) {
    currThread->start();
  }
}
void uartWork::stopThread() {
  if (currSerial->isOpen()) {
    currSerial->clear();
    currSerial->close();
    emit openError(false);
  }
}

void uartWork::timerOut() {
  if (sendArray.isEmpty())
    return;
  rcvDataTimer->stop();
  emit readyread(sendArray);
  sendArray.clear();
}

void uartWork::readyRead() {

  QByteArray data = currSerial->readAll();
  if (rcvDataTimer->isActive()) {
    rcvDataTimer->stop();
  }
  if (true == data.isEmpty())
    return;
  sendArray += data;
  rcvDataTimer->start(30);
}

void uartWork::openUart() {
  if (currSerial->isOpen()) {
    currSerial->clear();
    currSerial->close();
  }

  currSerial->setPortName(QString("COM%1").arg(currentCfg.portNum));
  currSerial->setBaudRate(currentCfg.baudRate);
  currSerial->setDataBits(currentCfg.dataBits);
  currSerial->setParity(currentCfg.paritys);
  currSerial->setStopBits(currentCfg.stopBits);
  currSerial->setFlowControl(currentCfg.flowCtrl);

  openFlag = currSerial->open(QIODevice::ReadWrite);
  emit openError(openFlag);
}

void uartWork::writeData(QByteArray data) {
  if ((true == currSerial->isOpen()) && (false == data.isEmpty())) {
    currSerial->write(data);
  }
}

void uartWork::errorOccurred(QSerialPort::SerialPortError error) {
  switch ((int)error) {
  case 0:
    /* 没有错误 */
    emit openError(true);
    break;
  case 1:
    /* 打开一个不存在的设备 */
    currSerial->close();
    emit errOccurred(QString("打开一个不存在的设备!"));
    emit openError(false);
    break;
  case 2:
    /* 无权限打开一个 */
    currSerial->close();
    emit errOccurred(QString("无权限打开设备!"));
    emit openError(false);
    break;
  case 3:
    /* 打开一个已经打开的设备 */
    emit errOccurred(QString("设备已打开!"));
    emit openError(false);
    break;
  case 7:
    /* 写入数据时发生的i/o错误 */
    currSerial->close();
    emit errOccurred(QString("写数据错误!"));
    openUart();
    break;
  case 8:
    /* 读取数据时发生了i/o错误 */
    currSerial->close();
    emit errOccurred(QString("读数据错误!"));
    openUart();
    break;
  case 9:
    /* 设备意外拔出,会发生i/o错误 */
    currSerial->close();
    emit errOccurred(QString("串口已拔出!"));
    emit openError(false);
    break;
  case 10:
    /* 系统不支持或者禁止的操作 */
    break;
  case 11:
    /* 未知错误 */
    currSerial->close();
    emit errOccurred(QString("发生未知错误!"));
    emit openError(false);
    break;
  case 12:
    /*
     * 发生了超时错误。
     * 此值已在QTserialport 5.2中引入。
     */
    // curlSerialPort->close();
    // emit errOccurred(QString("发生了超时错误!"));
    break;
  case 13:
    /*
     * 此错误发生在执行操作时，该操作只有在设备打开时才能成功执行。
     * 此值已在QTserialport 5.2中引入。 */
    break;
  }
}
